package app

import (
	"APT/internal/dao"
	"APT/internal/library/airhousePublicApi"
	"APT/internal/library/cache"
	"APT/internal/model/entity"
	"APT/internal/model/input/input_hotel"
	"APT/internal/model/input/input_refund"
	"APT/internal/service"
	"APT/utility/uuid"
	"context"
	"database/sql"
	"errors"
	"github.com/gogf/gf/v2/container/gvar"
	"github.com/gogf/gf/v2/database/gdb"
	"github.com/gogf/gf/v2/frame/g"
	"github.com/gogf/gf/v2/os/gtime"

	"github.com/gogf/gf/v2/errors/gerror"

	"APT/api/app/hotel"
)

func (c *ControllerHotel) PreOrderRefundDetail(ctx context.Context, req *hotel.PreOrderRefundDetailReq) (res *hotel.PreOrderRefundDetailRes, err error) {
	res = new(hotel.PreOrderRefundDetailRes)
	if res.PreRefundOut, err = service.HotelService().PreRefundOrderDetail(ctx, &req.PreRefundIn); err != nil {
		//err = gerror.New("服务器异常请稍后再试")
		return
	}
	if err = cache.Instance().Set(ctx, res.PreCancelOrderSn, res, gtime.M*10); err != nil {
		//err = gerror.New("服务器异常请稍后再试")
		return
	}
	return
}
func (c *ControllerHotel) RefundOrder(ctx context.Context, req *hotel.RefundOrderReq) (res *hotel.RefundOrderRes, err error) {
	var (
		PreRefundOut       *input_hotel.PreRefundOut
		NowPreRefundOut    *input_hotel.PreRefundOut
		ProCancelOrderInfo *gvar.Var
		CancelOrderSn      = uuid.CreateOrderCode("C")
		RoomReservation    []*entity.PmsAppReservation
		TX                 gdb.TX
		PmsAppStay         entity.PmsAppStay
	)
	if TX, err = g.DB().Begin(ctx); err != nil {
		return
	}
	defer func() {
		if err != nil {
			g.Log().Error(ctx, err)
			_ = TX.Rollback()
		} else {
			_ = TX.Commit()
		}
	}()
	if ProCancelOrderInfo, err = cache.Instance().Get(ctx, req.PreCancelOrderSn); err != nil {
		err = gerror.New("服务器异常请稍后再试")
		return
	}
	if err = ProCancelOrderInfo.Struct(&NowPreRefundOut); err != nil {
		err = gerror.New("服务器异常请稍后再试")
		return
	}
	if PreRefundOut, err = service.HotelService().PreRefundOrderDetail(ctx, &input_hotel.PreRefundIn{
		OrderSn: req.OrderSn,
	}); err != nil {
		err = gerror.New("服务器异常请稍后再试")
		return
	}
	if g.IsEmpty(NowPreRefundOut) {
		err = gerror.New("取消退款订单信息已过期，请重新申请取消退款")
		return
	}
	if PreRefundOut.RefundFee != NowPreRefundOut.RefundFee || PreRefundOut.RefundBalance != NowPreRefundOut.RefundBalance {
		err = gerror.New("退款信息发生变化")
		return
	}

	// 创建取消订单信息
	if _, err = dao.PmsAppCancelOrder.Ctx(ctx).TX(TX).Insert(g.MapStrAny{
		dao.PmsAppCancelOrder.Columns().CancelOrderSn: CancelOrderSn,
		dao.PmsAppCancelOrder.Columns().OrderSn:       PreRefundOut.OrderSn,
		dao.PmsAppCancelOrder.Columns().OutOrderSn:    PreRefundOut.OutOrderSn,
		dao.PmsAppCancelOrder.Columns().CancelAmount:  PreRefundOut.CancelFee,
		dao.PmsAppCancelOrder.Columns().CancelRate:    gvar.New(PreRefundOut.CancelRate).String(),
		dao.PmsAppCancelOrder.Columns().CancelAt:      gtime.Now().Format("Y-m-d H:i:s"),
		dao.PmsAppCancelOrder.Columns().CreatedAt:     gtime.Now().Format("Y-m-d H:i:s"),
		dao.PmsAppCancelOrder.Columns().UpdatedAt:     gtime.Now().Format("Y-m-d H:i:s"),
	}); err != nil {
		return
	}
	// 写入取消金额到订单中去
	if _, err = dao.PmsAppStay.Ctx(ctx).TX(TX).Where(dao.PmsAppStay.Columns().OrderSn, req.OrderSn).Data(g.MapStrAny{
		dao.PmsAppStay.Columns().CleanFee:     PreRefundOut.CancelFee,
		dao.PmsAppStay.Columns().OrderStatus:  "CANCEL",
		dao.PmsAppStay.Columns().RefundStatus: "DONE",
		dao.PmsAppStay.Columns().RefundAmount: PreRefundOut.RefundFee + PreRefundOut.RefundBalance + PreRefundOut.RefundCouponAmount,
		dao.PmsAppStay.Columns().RefundTime:   gtime.Now(),
	}).Update(); err != nil {
		return
	}
	if (PreRefundOut.RefundFee + PreRefundOut.RefundBalance + PreRefundOut.RefundCouponAmount) > 0 {
		if err = service.Refund().RefundOrder(ctx, &input_refund.RefundAmountInp{
			OrderSn:      PreRefundOut.OrderSn,
			RefundAmount: PreRefundOut.RefundFee + PreRefundOut.RefundBalance + PreRefundOut.RefundCouponAmount,
		}, TX); err != nil {
			return
		}
	}

	// 查询入住订单信息 进行取消操作
	if err = dao.PmsAppReservation.Ctx(ctx).Where(dao.PmsAppReservation.Columns().OrderSn, req.OrderSn).Scan(&RoomReservation); err != nil {
		return
	}
	for _, RoomReservationItem := range RoomReservation {
		if _, err = airhousePublicApi.UpdateRoomReservationPost(ctx, RoomReservationItem.Uuid, g.MapStrAny{
			"status": "cancelled",
			//"checkin_date":     RoomReservationItem.CheckinDate,
			//"checkout_date":    RoomReservationItem.CheckoutDate,
			//"cancellation_fee": PreRefundOut.CancelFee,
			//"booking_fee":      0,
		}); err != nil {
			return
		}
		// 更新入住订单信息
		if _, err = dao.PmsAppReservation.Ctx(ctx).TX(TX).Where(dao.PmsAppReservation.Columns().Uuid, RoomReservationItem.Uuid).Data(g.MapStrAny{
			dao.PmsAppReservation.Columns().OrderStatus:     "CANCEL",
			dao.PmsAppReservation.Columns().Status:          "cancelled",
			dao.PmsAppReservation.Columns().CancellationFee: PreRefundOut.CancelFee,
		}).Update(); err != nil {
			return
		}
	}

	// 酒店订单退款
	if err = dao.PmsAppStay.Ctx(ctx).Where(g.MapStrAny{
		dao.PmsAppStay.Columns().OrderSn: req.OrderSn,
	}).Scan(&PmsAppStay); err != nil && errors.Is(err, sql.ErrNoRows) {
		return
	}
	if g.IsEmpty(PmsAppStay) {
		err = gerror.New("该订单无需处理")
		return
	}
	if _, err = dao.PmsAppStayLog.Ctx(ctx).OmitEmptyData().Insert(&entity.PmsAppStayLog{
		OrderId:     PmsAppStay.Id,
		ActionWay:   "REFUND",
		Remark:      "订单退款",
		OperateType: "USER",
		OperateId:   PmsAppStay.MemberId,
	}); err != nil {
		return
	}
	return
}

func (c *ControllerHotel) OrderRefundDetail(ctx context.Context, req *hotel.OrderRefundDetailReq) (res *hotel.OrderRefundDetailRes, err error) {
	res = new(hotel.OrderRefundDetailRes)
	if res.RefundDetailModel, err = service.HotelService().RefundOrderDetail(ctx, req.RefundDetailInp); err != nil {
		return
	}
	return
}
